package com.ruoyi.oa.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.oa.domain.OaHumanClockTotal;
import com.ruoyi.oa.domain.OaPurchaseApply;
import com.ruoyi.oa.domain.bo.OaHumanSelectMonthBo;
import com.ruoyi.oa.domain.vo.OaFinanceBudgetVo;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaHumanClockCountBo;
import com.ruoyi.oa.domain.vo.OaHumanClockCountVo;
import com.ruoyi.oa.domain.OaHumanClockCount;
import com.ruoyi.oa.mapper.OaHumanClockCountMapper;
import com.ruoyi.oa.service.IOaHumanClockCountService;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 考勤记录Service业务层处理
 *
 * @author ruoyi
 * @date 2023-07-19
 */
@RequiredArgsConstructor
@Service
@EnableScheduling
public class OaHumanClockCountServiceImpl implements IOaHumanClockCountService {

    private final OaHumanClockCountMapper baseMapper;

    /**
     * 查询考勤记录
     */
    @Override
    public OaHumanClockCountVo queryById(String id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询考勤记录列表
     */
    @Override
    public TableDataInfo<OaHumanClockCountVo> queryPageList(OaHumanClockCountBo bo, PageQuery pageQuery) {

        LambdaQueryWrapper<OaHumanClockCount> lqw = buildQueryWrapper(bo);
        Page<OaHumanClockCountVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询考勤记录列表
     */
    @Override
    public List<OaHumanClockCountVo> queryList(OaHumanClockCountBo bo) {
        LambdaQueryWrapper<OaHumanClockCount> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<OaHumanClockCount> buildQueryWrapper(OaHumanClockCountBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<OaHumanClockCount> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getRuleId()), OaHumanClockCount::getRuleId, bo.getRuleId());
        lqw.eq(StringUtils.isNotBlank(bo.getClockShift()), OaHumanClockCount::getClockShift, bo.getClockShift());
        lqw.gt(bo.getStartDate() != null, OaHumanClockCount::getCreateTime, bo.getStartDate());
        lqw.lt(bo.getEndDate() != null, OaHumanClockCount::getCreateTime, bo.getEndDate());
        lqw.eq(bo.getDeptName() != null, OaHumanClockCount::getDeptName, bo.getDeptName());
        lqw.like(StringUtils.isNotBlank(bo.getApplyName()), OaHumanClockCount::getApplyName, bo.getApplyName());
        lqw.like(StringUtils.isNotBlank(bo.getAdjustName()), OaHumanClockCount::getAdjustName, bo.getAdjustName());
        lqw.eq(bo.getAbnormalCount() != null, OaHumanClockCount::getAbnormalCount, bo.getAbnormalCount());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), OaHumanClockCount::getAbnormalCount, bo.getStatus());
        lqw.eq(bo.getLateCount() != null, OaHumanClockCount::getLateCount, bo.getLateCount());
        lqw.eq(bo.getLateMinutes() != null, OaHumanClockCount::getLateMinutes, bo.getLateMinutes());
        lqw.eq(bo.getLeaveCount() != null, OaHumanClockCount::getLeaveCount, bo.getLeaveCount());
        lqw.eq(bo.getLeaveMinutes() != null, OaHumanClockCount::getLeaveMinutes, bo.getLeaveMinutes());
        lqw.eq(bo.getAbsentCount() != null, OaHumanClockCount::getAbsentCount, bo.getAbsentCount());
        lqw.eq(bo.getAbsentMinutes() != null, OaHumanClockCount::getAbsentMinutes, bo.getAbsentMinutes());
        lqw.eq(bo.getLackCount() != null, OaHumanClockCount::getLackCount, bo.getLackCount());
        lqw.eq(bo.getLackMinutes() != null, OaHumanClockCount::getLackMinutes, bo.getLackMinutes());
        lqw.eq(bo.getReplaceCount() != null, OaHumanClockCount::getReplaceCount, bo.getReplaceCount());
        lqw.orderByDesc(OaHumanClockCount::getCreateTime);
        return lqw;
        }

    /**
     * 新增考勤记录
     */
    @Override
    public Boolean insertByBo(OaHumanClockCountBo bo) {
        OaHumanClockCount add = BeanUtil.toBean(bo, OaHumanClockCount.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }



    /**
     * 修改考勤记录
     */
    @Override
    public Boolean updateByBo(OaHumanClockCountBo bo) {
        OaHumanClockCount update = BeanUtil.toBean(bo, OaHumanClockCount.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(OaHumanClockCount entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除考勤记录
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 根据用户查询当天打卡信息
     * @param userId
     * @return
     */
    @Override
    public OaHumanClockCountVo selectTodayVoByUserId(String userId){
        return baseMapper.selectTodayVoByUserId(userId);
    }

    /**
     * 获取昨天用户的打卡记录
     * @param userId
     * @return
     */
    @Override
    public OaHumanClockCountVo selectLastVoByUserId(String userId){
        return baseMapper.selectLastVoByUserId(userId);
    }



    @Override
    public int getReplaceCountByIdAndMonth(String userId, String month) {
        return baseMapper.getReplaceCountByIdAndMonth(userId,month);
    }

    /**
     * 根据打卡规则获取打卡记录
     * @param ruleId
     * @return
     */
    @Override
    public List<OaHumanClockCountVo> getTodayCountListByRuleId(String ruleId,String dateString){
        return baseMapper.getTodayCountListByRuleId(ruleId,dateString);
    }


    /**
     * 获取昨天打卡记录
     * @return
     */
    @Override
    public List<OaHumanClockCountVo> getLastCountList(){
        return baseMapper.getLastCountList();
    }

    /**
     * 获取今日打卡记录
     * @return
     */
    @Override
    public List<OaHumanClockCountVo> getTodayCountList() {
        return baseMapper.getTodayCountList();
    }

    /**
     * 打卡规则立即生效,会删除当天打卡记录
     */
    @Override
    public void updateCountRules(String ruleId){
//        List<OaHumanClockCountVo> todayCountListByRuleId = getTodayCountListByRuleId(ruleId);
//        List<String> collect = todayCountListByRuleId.stream().map(d -> d.getId()).collect(Collectors.toList());
//        Collection<String> list=collect;
//        deleteWithValidByIds(list,true);
    }


    @Override
    public TableDataInfo<OaHumanClockTotal> selectSumInfo(OaHumanClockCountBo bo, PageQuery pageQuery) {
        Page<OaHumanClockTotal> result = new Page<>();
        List<OaHumanClockTotal> oaHumanClockTotals = baseMapper.selectSumInfo(bo);
        int start = (pageQuery.getPageNum() - 1) * pageQuery.getPageSize();
        int end = Math.min(pageQuery.getPageNum() * pageQuery.getPageSize(), oaHumanClockTotals.size());
        result.setRecords(oaHumanClockTotals.subList(start,end));
        result.setSize(pageQuery.getPageSize());
        result.setCurrent(pageQuery.getPageNum());
        result.setTotal(oaHumanClockTotals.size());
        return TableDataInfo.build(result);
    }

    public TableDataInfo<OaHumanClockTotal> selectSumInfoForApp(OaHumanClockCountBo bo, PageQuery pageQuery) {
        SimpleDateFormat inputDateFormat = new SimpleDateFormat("yyyy-MM");
        SimpleDateFormat outputDateFormat = new SimpleDateFormat("yyyy/MM");
        Date date = null;
        try {
            date = inputDateFormat.parse(bo.getMonth());
            bo.setMonth(outputDateFormat.format(date));
            Page<OaHumanClockTotal> result = new Page<>();
            List<OaHumanClockTotal> oaHumanClockTotals = baseMapper.selectSumInfo(bo);
            if (StringUtils.isNotBlank(bo.getStatus())){
                if (bo.getStatus().equals("0")){
                    oaHumanClockTotals=oaHumanClockTotals.stream().filter(d-> "0".equals(d.getAbnormalCountTotal())).collect(Collectors.toList());
                }else if (bo.getStatus().equals("1")){
                    oaHumanClockTotals=oaHumanClockTotals.stream().filter(d-> !"0".equals(d.getAbnormalCountTotal())).collect(Collectors.toList());
                }else if (bo.getStatus().equals("2")){
                    //迟到
                    oaHumanClockTotals=oaHumanClockTotals.stream().filter(d-> !"0".equals(d.getLateCountTotal())).collect(Collectors.toList());
                }else if (bo.getStatus().equals("3")){
                    //早退
                    oaHumanClockTotals=oaHumanClockTotals.stream().filter(d-> !"0".equals(d.getLeaveCountTotal())).collect(Collectors.toList());
                }else if (bo.getStatus().equals("4")){
                    //缺卡
                    oaHumanClockTotals=oaHumanClockTotals.stream().filter(d-> !"0".equals(d.getLackCountTotal())).collect(Collectors.toList());
                }else if (bo.getStatus().equals("5")){
                    //旷工
                    oaHumanClockTotals=oaHumanClockTotals.stream().filter(d-> !"0".equals(d.getAbsentCountTotal())).collect(Collectors.toList());
                }else if (bo.getStatus().equals("6")){
                    //外勤
                    oaHumanClockTotals=oaHumanClockTotals.stream().filter(d-> !"0".equals(d.getOutsideCount())).collect(Collectors.toList());
                }
            }
            int start = (pageQuery.getPageNum() - 1) * pageQuery.getPageSize();
            int end = Math.min(pageQuery.getPageNum() * pageQuery.getPageSize(), oaHumanClockTotals.size());
            result.setRecords(oaHumanClockTotals.subList(start,end));
            result.setSize(pageQuery.getPageSize());
            result.setCurrent(pageQuery.getPageNum());
            result.setTotal(oaHumanClockTotals.size());
            return TableDataInfo.build(result);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public List<OaHumanClockTotal> exportSumInfo(OaHumanClockCountBo bo) {
        return  baseMapper.selectSumInfo(bo);
    }

    @Override
    public TableDataInfo<Object> getSumDetail(OaHumanSelectMonthBo bo, PageQuery pageQuery){
        Page<Object> result = new Page<>();
        JSONObject data=new JSONObject();
        if (ObjectUtil.isEmpty(bo.getType())){
            bo.setType(1);
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat minuteFormat = new SimpleDateFormat("HH:mm");
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<OaHumanClockCountVo> userIdList = baseMapper.selectGroupByUserId(bo);
        JSONArray array = new JSONArray();
        userIdList.forEach(d->{
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("userId",d.getUserId());
            jsonObject.put("userName",d.getUserName());
            jsonObject.put("ruleId",d.getRuleId());
            jsonObject.put("ruleName",d.getRuleName());
            jsonObject.put("deptName",d.getDeptName());
            jsonObject.put("roleName",d.getRoleName());
            bo.setUserId(d.getUserId());

            bo.setStartInfo(dateFormat.format(bo.getStartDate()));
            bo.setEndInfo(dateFormat.format(bo.getEndDate()));
//            dateFormat.format(bo.getStartDate());
            List<OaHumanClockCountVo> rangeList = baseMapper.selectByDateRange(bo);
            for (OaHumanClockCountVo oaHumanClockCountVo : rangeList) {
                String format = dateFormat.format(oaHumanClockCountVo.getCreateTime());
                if (oaHumanClockCountVo.getAdjustName().equals("正常(休息)")||oaHumanClockCountVo.getAdjustName().equals("核算中")){
                    jsonObject.put(format,oaHumanClockCountVo.getAdjustName());
                }else {
                    if (bo.getType()==(1)){
                        if (oaHumanClockCountVo.getStartTime()!=null&&oaHumanClockCountVo.getEndTime()!=null){
                            jsonObject.put(format,oaHumanClockCountVo.getStartStatus()+"-"+minuteFormat.format(oaHumanClockCountVo.getStartTime())
                                +";"+oaHumanClockCountVo.getEndStatus()+"-"+minuteFormat.format(oaHumanClockCountVo.getEndTime()));
                        }else if (oaHumanClockCountVo.getStartTime()==null&&oaHumanClockCountVo.getEndTime()!=null){
                            jsonObject.put(format,oaHumanClockCountVo.getStartStatus()
                                +";"+oaHumanClockCountVo.getEndStatus()+"-"+minuteFormat.format(oaHumanClockCountVo.getEndTime()));
                        }else if (oaHumanClockCountVo.getStartTime()!=null&&oaHumanClockCountVo.getEndTime()==null){
                            jsonObject.put(format,oaHumanClockCountVo.getStartStatus()+minuteFormat.format(oaHumanClockCountVo.getStartTime())
                                +";"+oaHumanClockCountVo.getEndStatus());
                        }else {
                            jsonObject.put(format,oaHumanClockCountVo.getAdjustName());
                        }
                    }else if (bo.getType()==(2)){
                        String temp="";
                        String item="";
                        if (oaHumanClockCountVo.getAbnormalCount()==0){
                            jsonObject.put(format,oaHumanClockCountVo.getAdjustName());
                        }else if (oaHumanClockCountVo.getLateCount()!=0){
                            if (StringUtils.isBlank(temp)){
                                item="";
                            }else {
                                item=";";
                            }
                            temp+=item+"迟到"+oaHumanClockCountVo.getLateMinutes()+"分钟";
                        }else if (oaHumanClockCountVo.getLeaveCount()!=0){
                            temp+=item+"早退"+oaHumanClockCountVo.getLeaveMinutes()+"分钟";
                        }else if (oaHumanClockCountVo.getAbsentCount()!=0){
                            temp+=item+"旷工"+oaHumanClockCountVo.getAbsentMinutes()+"分钟";
                        }else if (oaHumanClockCountVo.getLackCount()!=0){
                            temp+=item+"缺卡"+oaHumanClockCountVo.getLackCount()+"次";
                        }
                        jsonObject.put(format,temp);
                    }else if (bo.getType()==(3)){
                        String temp="";
                        String clockList = oaHumanClockCountVo.getClockList();
                        com.alibaba.fastjson.JSONArray clockListInfo = JSON.parseArray(clockList);
                        for (Object clock : clockListInfo ){
                            JSONObject clock1 = (JSONObject) clock;
                            if (!ObjectUtil.isEmpty(clock1.get("clockDate"))){
                                temp+=clock1.get("clockDate").toString()+";";
                            }
                        }
                        jsonObject.put(format,temp);
                    }
                }
            }
            array.add(jsonObject);
        });
        int start = (pageQuery.getPageNum() - 1) * pageQuery.getPageSize();
        int end = Math.min(pageQuery.getPageNum() * pageQuery.getPageSize(), array.size());
        result.setRecords(array.subList(start,end));
        result.setSize(pageQuery.getPageSize());
        result.setCurrent(pageQuery.getPageNum());
        result.setTotal(array.size());
        return TableDataInfo.build(result);
    }

    @Override
    public OaHumanClockCountVo selectLastByUserId(String userId, String dateString) {
        return baseMapper.selectLastByUserId(userId,dateString);
    }

    @Override
    public OaHumanClockTotal selectSumInfoByMonth(String month) {
        SimpleDateFormat inputDateFormat = new SimpleDateFormat("yyyy-MM");
        SimpleDateFormat outputDateFormat = new SimpleDateFormat("yyyy/MM");
        Date date = null;
        try {
            date = inputDateFormat.parse(month);
            String outputDate = outputDateFormat.format(date);
            return baseMapper.selectSumInfoByMonth(outputDate);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }


    @Override
    public OaHumanClockTotal selectSumInfoByMonthAndUserId(String month, String userId) {
        SimpleDateFormat inputDateFormat = new SimpleDateFormat("yyyy-MM");
        SimpleDateFormat outputDateFormat = new SimpleDateFormat("yyyy/MM");
        Date date = null;
        try {
            date = inputDateFormat.parse(month);
            String outputDate = outputDateFormat.format(date);
            return baseMapper.selectSumInfoByMonthAndUserId(outputDate,userId);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public OaHumanClockTotal selectSumInfoByDate(String date) {
        return baseMapper.selectSumInfoByMonth(date);
    }

    @Override
    public List<OaHumanClockCountVo> selectCountByDate(String dateString) {
        return baseMapper.selectCountByDate(dateString);
    }

    @Override
    public int cleanEndTime(String id) {
        return baseMapper.cleanEndTime(id);
    }

    @Override
    public int cleanStartTime(String id) {
        return baseMapper.cleanStartTime(id);
    }

    @Override
    public TableDataInfo<OaHumanClockCountVo> queryPerDaySum(OaHumanClockCountBo bo, PageQuery pageQuery) {
        List<OaHumanClockCountVo> oaHumanClockCountVos = baseMapper.queryPerDaySum(bo);
        if (StringUtils.isNotBlank(bo.getStatus())){
            if (bo.getStatus().equals("0")){
                oaHumanClockCountVos=oaHumanClockCountVos.stream().filter(d-> d.getAbnormalCount()==0).collect(Collectors.toList());
            }else if (bo.getStatus().equals("1")){
                oaHumanClockCountVos=oaHumanClockCountVos.stream().filter(d-> d.getAbnormalCount()!=0).collect(Collectors.toList());
            }else if (bo.getStatus().equals("2")){
                //迟到
                oaHumanClockCountVos=oaHumanClockCountVos.stream().filter(d-> d.getLateCount()!=0).collect(Collectors.toList());
            }else if (bo.getStatus().equals("3")){
                //早退
                oaHumanClockCountVos=oaHumanClockCountVos.stream().filter(d-> d.getLeaveCount()!=0).collect(Collectors.toList());
            }else if (bo.getStatus().equals("4")){
                //缺卡
                oaHumanClockCountVos=oaHumanClockCountVos.stream().filter(d-> d.getLackCount()!=0).collect(Collectors.toList());
            }else if (bo.getStatus().equals("5")){
                //旷工
                oaHumanClockCountVos=oaHumanClockCountVos.stream().filter(d-> d.getAbsentCount()!=0).collect(Collectors.toList());
            }else if (bo.getStatus().equals("6")){
                //外勤
                oaHumanClockCountVos=oaHumanClockCountVos.stream().filter(d-> d.getIsOutside()).collect(Collectors.toList());
            }
        }

        Page<OaHumanClockCountVo> result = new Page<>();
        result.setTotal(oaHumanClockCountVos.size());

        int start = (pageQuery.getPageNum() - 1) * pageQuery.getPageSize();
        int end = Math.min(pageQuery.getPageNum() * pageQuery.getPageSize(), oaHumanClockCountVos.size());
        if (start>oaHumanClockCountVos.size()){
            return TableDataInfo.build(new Page<>());
        }
        oaHumanClockCountVos = oaHumanClockCountVos.subList(start, end);
        result.setRecords(oaHumanClockCountVos);
        result.setCurrent(pageQuery.getPageNum());
        result.setSize(pageQuery.getPageSize());
        return TableDataInfo.build(result);
    }

    /**
     * 根据月份统计出来考勤正常的人数
     * @param moth
     * @return
     */
    @Override
    public Map<String, Object> SelectNormalUserByMonth(String month) {
        Map<String, Object> data = new HashMap<>();
        SimpleDateFormat inputDateFormat = new SimpleDateFormat("yyyy-MM");
        SimpleDateFormat outputDateFormat = new SimpleDateFormat("yyyy/MM");
        Date date = null;
        try {
            date = inputDateFormat.parse(month);
            String outputDate = outputDateFormat.format(date);
            Integer integer = baseMapper.SelectNormalUserByMonth(outputDate);
            data.put("normalData",integer);
            Integer integer2 = baseMapper.SelectAbnormalUserByMonth(outputDate);
            data.put("abnormalData",integer2);
            return data;
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    public Map<String, Object> SelectNormalUserByDate(String date) {
        Map<String, Object> data = new HashMap<>();
        Integer integer = baseMapper.SelectNormalUserByMonth(date);
        data.put("normalData",integer);
        Integer integer2 = baseMapper.SelectAbnormalUserByMonth(date);
        data.put("abnormalData",integer2);
        return data;
    }

    /**
     * 通过月份以及用户id获取用户当月打卡条数
     * @param userId
     * @param dateString
     * @return
     */
    @Override
    public Integer getUserClockCountByMonth(String userId, String dateString) {
        SimpleDateFormat inputDateFormat = new SimpleDateFormat("yyyy-MM");
        SimpleDateFormat outputDateFormat = new SimpleDateFormat("yyyy/MM");
        Date date = null;
        try {
            date = inputDateFormat.parse(dateString);
            String outputDate = outputDateFormat.format(date);
            Integer count = baseMapper.getUserClockCountByMonth(userId, outputDate);
            return count;

        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取某人本月外勤次数
     * @param month
     * @param userId
     * @return
     */
    @Override
    public Integer getOutSideCount(String month, String userId) {
        SimpleDateFormat inputDateFormat = new SimpleDateFormat("yyyy-MM");
        SimpleDateFormat outputDateFormat = new SimpleDateFormat("yyyy/MM");
        Date date = null;
        try {
            date = inputDateFormat.parse(month);
            String outputDate = outputDateFormat.format(date);
            return baseMapper.getOutSideCount(outputDate, userId);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Integer getLeaveCount(String month, String userId) {
        SimpleDateFormat inputDateFormat = new SimpleDateFormat("yyyy-MM");
        SimpleDateFormat outputDateFormat = new SimpleDateFormat("yyyy/MM");
        Date date = null;
        try {
            date = inputDateFormat.parse(month);
            String outputDate = outputDateFormat.format(date);
            return baseMapper.getLeaveCount(outputDate, userId);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    public List<OaHumanClockCountVo> getLeaveData(String month, String userId){
        return baseMapper.getLeaveData(month, userId);
    }
}
